#include "httplib.h"
#include "data.hpp"


namespace order_sys{
#define SERVER_PORT 4090
#define Default_Path "./Default_Path"
  class Server{
  private:
    int _port = SERVER_PORT;
    std::string _Default_Path = Default_Path;
    httplib::Server* _server;
    static TableDish* _table_dish;
    static TableOrder* _table_order;
  private:
    //菜品新增业务的处理函数
    static void DishInsert(const httplib::Request& req, httplib::Response& rsp){ //回调函数只能有两个参数,所以函数只能设置为静态的
    //先获取到要新增菜品的信息,保存在请求正文中  req.body --json格式的字符串
    // req.body == "{"name":"红烧肉", "price":1000, "info":"好吃" }"
    //对正文进行json反序列化,得到要新增的各个菜品信息在Json::Value
      Json::FastWriter writer;
      Json::Value dish;
      Json::Reader reader;
      Json::Value err;
      bool ret = reader.parse(req.body, dish);
      if(ret == false){ //出错的情况下，要给客户端响应什么数据
        err["result"] = false;
        err["reason"] = "提交的菜品信息有误!"; //响应的信息
        rsp.status = 400; //bad request 响应状态码
        rsp.body = writer.write(err);//响应格式是一个json格式的字符串,所以要进行json序列化
        rsp.set_header("Content-Type", "application/json");
        std::cout << rsp.body << std::endl;
        return ;
      }
      //调用数据管理模块对象,实现数据到数据库中的新增
      ret = _table_dish->Insert(dish);
      if(ret == false){ 
        err["result"] = false;
        err["reason"] = "菜品信息插入数据库失败!"; //响应的信息
        rsp.status = 500; //服务器内部错误, 响应状态码
        rsp.body = writer.write(err);//响应格式是一个json格式的字符串,所以要进行json序列化
        rsp.set_header("Content-Type", "application/json");
        std::cout << rsp.body << std::endl;
        return ;
      }
      //返回执行结果
      rsp.status = 200;
    }
    static void DishDelete(const httplib::Request& req, httplib::Response& rsp){
      //1. 明确删除哪个菜品，获取到要删除菜品的id
      int dish_id = std::stoi(req.matches[1]);
      //2. 调用数据管理模块，从数据库中删除数据
      bool ret = _table_dish->Delete(dish_id);
      if(ret == false){ 
        Json::FastWriter writer;
        Json::Value err;
        err["result"] = false;
        err["reason"] = "数据库删除菜品信息失败!"; //响应的信息
        rsp.status = 500; //服务器内部错误, 响应状态码
        rsp.body = writer.write(err);//响应格式是一个json格式的字符串,所以要进行json序列化
        rsp.set_header("Content-Type", "application/json");
        std::cout << rsp.body << std::endl;
        return ;
      }
      //3. 响应处理结果
      rsp.status = 200;
    }
    static void DishUpdate(const httplib::Request& req, httplib::Response& rsp){
      //1.获取要修改的菜品id
      int dish_id = std::stoi(req.matches[1]);
      //2.获取到新的菜品信息
      Json::FastWriter writer;
      Json::Value dish;
      Json::Reader reader;
      Json::Value err;
      bool ret = reader.parse(req.body, dish);
      if(ret == false){ //出错的情况下，要给客户端响应什么数据
        err["result"] = false;
        err["reason"] = "更新的菜品信息有误!"; //响应的信息
        rsp.status = 400; //bad request 响应状态码
        rsp.body = writer.write(err);//响应格式是一个json格式的字符串,所以要进行json序列化
        rsp.set_header("Content-Type", "application/json");
        std::cout << rsp.body << std::endl;
        return ;
      }
      //3.对数据库中的菜品信息进行更新
      ret = _table_dish->Update(dish_id, dish);
      if(ret == false){ 
        err["result"] = false;
        err["reason"] = "菜品信息更新数据库失败!"; //响应的信息
        rsp.status = 500; //服务器内部错误, 响应状态码
        rsp.body = writer.write(err);//响应格式是一个json格式的字符串,所以要进行json序列化
        rsp.set_header("Content-Type", "application/json");
        std::cout << rsp.body << std::endl;
        return ;
      }
      //4.返回处理结果
      rsp.status = 200;
    }
    static void DishGetAll(const httplib::Request& req, httplib::Response& rsp){
     // 1.从数据库取出所有菜品信息
      Json::FastWriter writer;
      Json::Value dish;
      Json::Value err;
      bool ret = _table_dish->GetAll(&dish);
      if(ret == false){ 
        err["result"] = false;
        err["reason"] = "从数据库获取所有菜品信息失败!"; //响应的信息
        rsp.status = 500; //服务器内部错误, 响应状态码
        rsp.body = writer.write(err);//响应格式是一个json格式的字符串,所以要进行json序列化
        rsp.set_header("Content-Type", "application/json");
        std::cout << rsp.body << std::endl;
        return ;
      }
     // 2.将菜品信息序列化成为字符串，放入响应正文中
     rsp.body = writer.write(dish);
     rsp.status = 200;
     rsp.set_header("Content-Type", "application/json");
    }

    static void DishGetOne(const httplib::Request& req, httplib::Response& rsp){
     // 0.明确要获取的菜品id
      int dish_id = std::stoi(req.matches[1]);
     // 1.从数据库取出指定菜品信息
      Json::FastWriter writer;
      Json::Value dish;
      Json::Value err;
      bool ret = _table_dish->GetOne(dish_id, &dish);
      if(ret == false){ 
        err["result"] = false;
        err["reason"] = "从数据库获取指定菜品信息失败!"; //响应的信息
        rsp.status = 500; //服务器内部错误, 响应状态码
        rsp.body = writer.write(err);//响应格式是一个json格式的字符串,所以要进行json序列化
        rsp.set_header("Content-Type", "application/json");
        std::cout << rsp.body << std::endl;
        return ;
      }
     // 2.将菜品信息序列化成为字符串，放入响应正文中
     rsp.body = writer.write(dish);
     rsp.status = 200;
     rsp.set_header("Content-Type", "application/json");
    }
  private:
    //订单新增业务的处理函数
    static void OrderInsert(const httplib::Request& req, httplib::Response& rsp){ //回调函数只能有两个参数,所以函数只能设置为静态的
    //先获取到要新增订单的信息,保存在请求正文中  req.body --json格式的字符串
    //对正文进行json反序列化,得到要新增的各个订单信息在Json::Value
      Json::FastWriter writer;
      Json::Value order;
      Json::Reader reader;
      Json::Value err;
      bool ret = reader.parse(req.body, order);
      if(ret == false){ //出错的情况下，要给客户端响应什么数据
        err["result"] = false;
        err["reason"] = "提交的订单信息有误!"; //响应的信息
        rsp.status = 400; //bad request 响应状态码
        rsp.body = writer.write(err);//响应格式是一个json格式的字符串,所以要进行json序列化
        rsp.set_header("Content-Type", "application/json");
        std::cout << rsp.body << std::endl;
        return ;
      }
      //调用数据管理模块对象,实现数据到数据库中的新增
      ret = _table_order->Insert(order);
      if(ret == false){ 
        err["result"] = false;
        err["reason"] = "订单信息插入数据库失败!"; //响应的信息
        rsp.status = 500; //服务器内部错误, 响应状态码
        rsp.body = writer.write(err);//响应格式是一个json格式的字符串,所以要进行json序列化
        rsp.set_header("Content-Type", "application/json");
        std::cout << rsp.body << std::endl;
        return ;
      }
      //返回执行结果
      rsp.status = 200;
    }
    static void OrderDelete(const httplib::Request& req, httplib::Response& rsp){
      //1. 明确删除哪个订单，获取到要删除订单的id
      int order_id = std::stoi(req.matches[1]);
      //2. 调用数据管理模块，从数据库中删除数据
      bool ret = _table_order->Delete(order_id);
      if(ret == false){ 
        Json::FastWriter writer;
        Json::Value err;
        err["result"] = false;
        err["reason"] = "数据库删除订单信息失败!"; //响应的信息
        rsp.status = 500; //服务器内部错误, 响应状态码
        rsp.body = writer.write(err);//响应格式是一个json格式的字符串,所以要进行json序列化
        rsp.set_header("Content-Type", "application/json");
        std::cout << rsp.body << std::endl;
        return ;
      }
      //3. 响应处理结果
      rsp.status = 200;
    }
    static void OrderUpdate(const httplib::Request& req, httplib::Response& rsp){
      //1.获取要修改的订单id
      int order_id = std::stoi(req.matches[1]);
      //2.获取到新的订单信息
      Json::FastWriter writer;
      Json::Value order;
      Json::Reader reader;
      Json::Value err;
      bool ret = reader.parse(req.body, order);
      if(ret == false){ //出错的情况下，要给客户端响应什么数据
        err["result"] = false;
        err["reason"] = "更新的订单信息有误!"; //响应的信息
        rsp.status = 400; //bad request 响应状态码
        rsp.body = writer.write(err);//响应格式是一个json格式的字符串,所以要进行json序列化
        rsp.set_header("Content-Type", "application/json");
        std::cout << rsp.body << std::endl;
        return ;
      }
      //3.对数据库中的订单信息进行更新
      ret = _table_order->Update(order_id, order);
      if(ret == false){ 
        err["result"] = false;
        err["reason"] = "订单信息更新数据库失败!"; //响应的信息
        rsp.status = 500; //服务器内部错误, 响应状态码
        rsp.body = writer.write(err);//响应格式是一个json格式的字符串,所以要进行json序列化
        rsp.set_header("Content-Type", "application/json");
        std::cout << rsp.body << std::endl;
        return ;
      }
      //4.返回处理结果
      rsp.status = 200;
    }
    static void OrderGetAll(const httplib::Request& req, httplib::Response& rsp){
     // 1.从数据库取出所有订单信息
      Json::FastWriter writer;
      Json::Value order;
      Json::Value err;
      bool ret = _table_order->GetAll(&order);
      if(ret == false){ 
        err["result"] = false;
        err["reason"] = "从数据库获取所有订单信息失败!"; //响应的信息
        rsp.status = 500; //服务器内部错误, 响应状态码
        rsp.body = writer.write(err);//响应格式是一个json格式的字符串,所以要进行json序列化
        rsp.set_header("Content-Type", "application/json");
        std::cout << rsp.body << std::endl;
        return ;
      }
     // 2.将订单信息序列化成为字符串，放入响应正文中
     rsp.body = writer.write(order);
     rsp.status = 200;
     rsp.set_header("Content-Type", "application/json");
    }

    static void OrderGetOne(const httplib::Request& req, httplib::Response& rsp){
     // 0.明确要获取的订单id
      int order_id = std::stoi(req.matches[1]);
     // 1.从数据库取出指定订单信息
      Json::FastWriter writer;
      Json::Value order;
      Json::Value err;
      bool ret = _table_order->GetOne(order_id, &order);
      if(ret == false){ 
        err["result"] = false;
        err["reason"] = "从数据库获取指定订单信息失败!"; //响应的信息
        rsp.status = 500; //服务器内部错误, 响应状态码
        rsp.body = writer.write(err);//响应格式是一个json格式的字符串,所以要进行json序列化
        rsp.set_header("Content-Type", "application/json");
        std::cout << rsp.body << std::endl;
        return ;
      }
     // 2.将订单信息序列化成为字符串，放入响应正文中
     rsp.body = writer.write(order);
     rsp.status = 200;
     rsp.set_header("Content-Type", "application/json");
    }
      
  public:
    Server(int port = SERVER_PORT):_port(port){
    }

    bool RunServer(){
      _table_dish = new TableDish();
      _table_order = new TableOrder();
      _server = new httplib::Server(); //实例化httplib的server对象

      _server->set_mount_point("/",_Default_Path); //设置静态资源根目录

      _server->Post(R"(/dish)", DishInsert); // 当服务器收到了Post请求方法的 /dish请求, 则调用DishInsert函数进行处理
      _server->Delete(R"(/dish/(\d+))", DishDelete);
      _server->Put(R"(/dish/(\d+))", DishUpdate);
      _server->Get(R"(/dish)", DishGetAll);
      _server->Get(R"(/dish/(\d+))", DishGetOne);

      _server->Post(R"(/order)", OrderInsert);
      _server->Delete(R"(/order/(\d+))", OrderDelete);
      _server->Put(R"(/order/(\d+))", OrderUpdate);
      _server->Get(R"(/order)", OrderGetAll);
      _server->Get(R"(/order/(\d+))", OrderGetOne);
      
      _server->listen("0.0.0.0", _port);
      return true;
    }

  };
  TableDish* Server::_table_dish = nullptr; 
  TableOrder* Server::_table_order = nullptr;
}
